package com.yrd.fssync;

import java.io.File;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.Date;

import org.apache.commons.io.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.yrd.common.webui.HttpEngine;
import com.yrd.fssync.core.Context;
import com.yrd.fssync.core.FileSystemListener;
import com.yrd.fssync.core.FileSystemMonitor;
import com.yrd.fssync.core.FileSystemMonitorManager;
import com.yrd.fssync.core.ISyncer;
import com.yrd.fssync.core.SyncEngine;
import com.yrd.fssync.core.Tray;
import com.yrd.fssync.core.Utils;
import com.yrd.fssync.plugin.FileSyncer;
import com.yrd.fssync.plugin.FtpSyncer;

/**
 *
 */
public class App
{
	Context context;
	boolean syncing;
	Document doc;
	
	public App() {
	}
	
	public void refresh() throws Exception{
		if(context!=null){
			stop();
		}
		context = new Context();
		Utils.setContext(context);
		context.setApp(this);
		File cfgFile = new File("config.xml");
		if(!cfgFile.exists()){
			InputStream ism = this.getClass().getClassLoader().getResourceAsStream("res/config.xml");
			FileUtils.copyInputStreamToFile(ism, cfgFile);
		}
		doc = Jsoup.parse(cfgFile, "UTF-8");
		Utils.printfln("读取配置文件");
		short webuiPort = Short.parseShort(doc.select("webui port").get(0).text());
		HttpEngine httpEngine = HttpEngine.create(new InetSocketAddress(webuiPort), "com.yrd.fssync.webui.servlet");
		context.setHttpEngine(httpEngine);
		new Tray(context);
		
		FileSystemMonitorManager fileSystemMonitorManager = new FileSystemMonitorManager(context);
		Elements pairs = doc.select("pair");
		for(Element pair : pairs){
			Element listener = pair.select("listener").get(0);
			String listenerId = listener.attr("id");
			String localBase = Utils.standardUnixDirName(listener.select("localBase").text());
			FileSystemListener fileSystemListener = new FileSystemListener(context, localBase);
			FileSystemMonitor fileSystemMonitor = new FileSystemMonitor(context,listenerId,localBase,fileSystemListener);
			fileSystemMonitorManager.add(fileSystemMonitor);

			Elements syncerElems = doc.select("syncer");
			for(Element syncerElem : syncerElems){
				String type = syncerElem.attr("type");
				if("ftp".equalsIgnoreCase(type)){
					String syncerId = syncerElem.attr("id");
					String ip = syncerElem.select("ip").get(0).text();
					short port = Short.parseShort(syncerElem.select("port").get(0).text());
					String name = syncerElem.select("name").get(0).text();
					String passwd = syncerElem.select("passwd").get(0).text();
					String remoteBase = Utils.standardUnixDirName(syncerElem.select("remoteBase").get(0).text());
					ISyncer syncer = new FtpSyncer(ip, port, name, passwd,remoteBase);
					SyncEngine syncEngine = new SyncEngine(context,syncerId,syncer);
					fileSystemMonitor.addSyncEngine(syncEngine);
				}else if("file".equalsIgnoreCase(type)){
					String syncerId = syncerElem.attr("id");
					String remoteBase = Utils.standardUnixDirName(syncerElem.select("remoteBase").get(0).text());
					ISyncer syncer = new FileSyncer(remoteBase);
					SyncEngine syncEngine = new SyncEngine(context,syncerId,syncer);
					fileSystemMonitor.addSyncEngine(syncEngine);
				}
			}
			
		}
		start();
	}
	
	public void start(){
		if(syncing)return;
		syncing = true;
		context.getTray().start();
		try {
			context.getHttpEngine().start();
			context.getFileSystemMonitorManager().start();
			context.getTray().info("文件同步器", "启动完成");
			context.getTray().statusNormal();
		} catch (Exception e) {
			e.printStackTrace();
			context.getTray().info("致命错误", e.getLocalizedMessage());
			context.getTray().statusError();
			sleep(5000);
			System.exit(1);
		}
	}
	public void stop(){
		if(!syncing)return;
		syncing = false;
		try {
			context.getFileSystemMonitorManager().stop();
			HttpEngine.distroy();
			context.setHttpEngine(null);
			context.getTray().stop();
		} catch (Exception e) {
			e.printStackTrace();
			context.getTray().info("文件同步器", "出错，强行关闭");
			sleep(1000);
			System.exit(1);
		}
	}

	private void sleep(long time){
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) throws Exception {
		App app = new App();
		app.refresh();
/*		
*/		
		
/*		File dir = new File("E:\\testDir");
		//监听器
		FileAlterationMonitor monitor = new FileAlterationMonitor();
		
		//1. 不指定监听类型, 则会监听两种类型: 文件 及 子文件夹
		
		//2. 指定监听类型,只指定监听文件的类型,例如 ".txt"文件, 则在子文件夹下的".txt"文件变化不会监听,只会监听E:\\testDir下的文件变化
		IOFileFilter fileFileter = FileFilterUtils.and(FileFilterUtils.fileFileFilter(),FileFilterUtils.suffixFileFilter(".txt"));
		
		//3. 指定监听类型,只指定监听文件夹,则文件的变化不会监听到(不论是在文件夹下的还是在子文件夹下的)
		IOFileFilter dirFilter = FileFilterUtils.and(FileFilterUtils.directoryFileFilter(),HiddenFileFilter.VISIBLE);
			
		//4. 指定两种监听类型,文件及文件夹,则会监听两种,文件夹及文件(不论是在文件夹下的还是在子文件夹下的)
		IOFileFilter filter = FileFilterUtils.or(fileFileter,dirFilter);
		
		//观察者
		FileAlterationObserver observer = new FileAlterationObserver(dir ,HiddenFileFilter.VISIBLE);
		observer.addListener(new FileSystemListener());
		
		monitor.addObserver(observer);
		try {
			//开始监听
			monitor.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
*/	
		
	}
}
